
#ifndef ILOGGER_HPP
#define ILOGGER_HPP


#include <string>
#include <vector>
#include <tuple>
#include <time.h>


#if defined(_WIN32)
#	define U_OS_WINDOWS
#else
#   define U_OS_LINUX
#endif


namespace iLogger{

    using namespace std;

    enum class LogLevel : int{
        Debug   = 5,
        Verbose = 4,
        Info    = 3,
        Warning = 2,
        Error   = 1,
        Fatal   = 0
    };

    //log
    #define INFOD(...)			iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Debug, __VA_ARGS__)
    #define INFOV(...)			iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Verbose, __VA_ARGS__)
    #define INFO(...)			iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Info, __VA_ARGS__)
    #define INFOW(...)			iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Warning, __VA_ARGS__)
    #define INFOE(...)			iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Error, __VA_ARGS__)
    #define INFOF(...)			iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Fatal, __VA_ARGS__)

    //获取日期
    string date_now();
    //获取时间
    string time_now();
    //获取时间
    string gmtime_now();
	string gmtime(time_t t);
	time_t gmtime2ctime(const string& gmt);
    //睡眠
    void sleep(int ms);

    //判断是否是文件
    bool isfile(const string& file);
    //创建目录
    bool mkdir(const string& path);
    //创建多级目录
    bool mkdirs(const string& path);
    //删除文件
    bool delete_file(const string& path);
    //删除文件夹，ignore_fail是否忽略删除失败
    bool rmtree(const string& directory, bool ignore_fail=false);
    //判断文件是否存在
    bool exists(const string& path);
    //类似printf一样把一些字符串拼起来
    string format(const char* fmt, ...);

    FILE* fopen_mkdirs(const string& path, const string& mode);
    //获取path的文件名，include_suffix是否包含后缀
    string file_name(const string& path, bool include_suffix=true);
    //获取path的父路径
    string directory(const string& path);
    //时间戳毫秒级
    long long timestamp_now();
    //时间戳纳秒级
    double timestamp_now_float();
    //文件上一次被修改的时间
    time_t last_modify(const string& file);
    //读取二进制文件到vector<uint8_t>
    vector<uint8_t> load_file(const string& file);
    //将txt内容全部读取到一个str
    string load_text_file(const string& file);
    //获取文件大小
    size_t file_size(const string& file);
    //判断一个字符是否以with开头
    bool begin_with(const string& str, const string& with);
    //判断一个字符是否以with结尾
	bool end_with(const string& str, const string& with);
    //分割字符串
    vector<string> split_string(const string& str, const std::string& spstr);
    string replace_string(const string& str, const string& token, const string& value, int nreplace=-1, int* out_num_replace=nullptr);

    //   abcdefg.pnga          *.png      > false
	//   abcdefg.png           *.png      > true
	//   abcdefg.png          a?cdefg.png > true
    //类似正则表达式的部分功能
	bool pattern_match(const char* str, const char* matcher, bool igrnoe_case = true);
    //遍历文件夹下的文件
    vector<string> find_files(
        const string& directory, 
        const string& filter = "*", bool findDirectory = false, bool includeSubDirectory = false);

    string align_blank(const string& input, int align_size, char blank=' ');
    bool save_file(const string& file, const vector<uint8_t>& data, bool mk_dirs = true);
    bool save_file(const string& file, const string& data, bool mk_dirs = true);
	bool save_file(const string& file, const void* data, size_t length, bool mk_dirs = true);

    // 捕获：SIGINT(2)、SIGQUIT(3)
    int while_loop();

    // 关于logger的api
    //得到log等级字符
    const char* level_string(LogLevel level);
    //设置Log保存路径
    void set_logger_save_directory(const string& loggerDirectory);
    //设置Log目录
    void set_log_level(LogLevel level);
    LogLevel get_log_level();
    void __log_func(const char* file, int line, LogLevel level, const char* fmt, ...);
    void destroy_logger();

    string base64_decode(const string& base64);
    string base64_encode(const void* data, size_t size);

    inline int upbound(int n, int align = 32){return (n + align - 1) / align * align;}
    string join_dims(const vector<int64_t>& dims);
};


#endif // ILOGGER_HPP